{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "31fe478a",
   "metadata": {},
   "source": [
    "# python基础入门8_ 类面向对象\n",
    "Python中的类是一种面向对象编程的概念，它允许我们根据属性和方法来模拟现实世界中的事物。类的定义包括实例属性、类属性、方法和类的继承等基础知识。此外，Python还支持类的构造方法、参数、继承、方法重写等方面的知识，以及类的特殊属性和方法，如私有属性和私有方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0db673e4",
   "metadata": {},
   "source": [
    "## 类的定义\n",
    "\n",
    "要定义一个类，你需要在Python中使用关键字\"class\"，后接类名和冒号。类体需要缩进，并通常在冒号之后立即开始。类的主要组成部分包括变量（或称为属性）和方法。变量用于存储数据，而方法则用于执行特定的操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "54e108f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Person:\n",
    "    def __init__(self, name, age):  # 构造函数\n",
    "        self.name = name  # 实例属性\n",
    "        self.age = age  # 实例属性\n",
    "\n",
    "    def introduce(self):  # 实例方法\n",
    "        print(\"My name is \" + self.name)\n",
    "\n",
    "    def birthday(self):  # 实例方法\n",
    "        self.age += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7642cb24",
   "metadata": {},
   "source": [
    "在这个例子中，____init____是一个特殊的方法，称为构造函数，当创建类的一个新实例时，它会自动调用。self是对类实例的引用，用于访问类的属性和方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b657c91",
   "metadata": {},
   "source": [
    "## 类的实例（对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "caf492a8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tom\n",
      "20\n",
      "My name is Tom\n"
     ]
    }
   ],
   "source": [
    "# 创建一个Person对象\n",
    "person1 = Person(\"Tom\", 20)\n",
    "# 访问对象的属性\n",
    "print(person1.name)  # 输出： Tom\n",
    "print(person1.age)   # 输出： 20\n",
    "# 调用对象的方法\n",
    "person1.introduce()  # 输出： My name is Tom\n",
    "person1.birthday()   # person1的年龄增加1，现在变为21岁"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6a1ff5a",
   "metadata": {},
   "source": [
    "## 类的访问限制\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c0cfd63",
   "metadata": {},
   "source": [
    "在Python中，类的成员包括数据成员和类的方法。\n",
    "\n",
    "这些成员可以被分为公有、私有和保护三种类型，用以控制对其访问的权限。\n",
    "\n",
    "类的公有成员可以在任何时候被访问，而在类的外部通过类名直接进行访问。\n",
    "\n",
    "\n",
    "类的私有成员，如属性或方法，则用两个下划线前缀来声明，表示这些成员仅能被本类访问，无法在类的外部进行访问或者继承。\n",
    "\n",
    "例如，如果一个类中定义了如下的私有属性：\n",
    "__private_attrs，那么这个属性就只能在这个类的内部被访问，无法在类的外部通过类名直接进行访问。\n",
    "\n",
    "\n",
    "此外，Python还提供了一种\"保护成员\"的机制，其命名方式是在变量或方法的名称前加上一个下划线。这种类型的成员只能被本类及其子类访问，而无法在类的外部进行访问。\n",
    "\n",
    "\n",
    "例如，如果我们有一个名为\"Person\"的类，我们可以这样定义和使用它的公有和私有属性和方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "89248686",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Person:\n",
    "    def __init__(self, name, age):  # 构造函数\n",
    "        self.name = name  # 实例属性（公有）\n",
    "        self.__age = age  # 实例属性（私有）\n",
    "\n",
    "    def introduce(self):  # 实例方法（公有）\n",
    "        print(\"My name is \" + self.name)\n",
    "\n",
    "    def birthday(self):  # 实例方法（公有）\n",
    "        self.__age += 1\n",
    "    \n",
    "    def getage(self):\n",
    "        return self.__age"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e04db53",
   "metadata": {},
   "source": [
    "在这个例子中，\"name\"是一个公有属性，可以在类的外部通过类名直接进行访问；\"__age\"是一个私有属性，只能在类的内部进行访问。同样，\"introduce\"和\"birthday\"都是公有方法，既可以在类的外部通过实例对象进行调用，也可以在类的内部进行调用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "a40ddec5",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1 = Person(\"jack\",18)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "76cea551",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "jack\n"
     ]
    }
   ],
   "source": [
    "print(p1.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "b651cec1",
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'Person' object has no attribute '__age'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_19416/3821545598.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mp1\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__age\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'Person' object has no attribute '__age'"
     ]
    }
   ],
   "source": [
    "print(p1.__age)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "bfa69e09",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My name is jack\n"
     ]
    }
   ],
   "source": [
    "p1.introduce()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "000a0d09",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1.birthday()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "93256cfb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "19"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p1.getage()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5d7fcc6",
   "metadata": {},
   "source": [
    "## 类的继承"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "724f6ecc",
   "metadata": {},
   "source": [
    "在Python中，一个类可以继承另一个类的属性和方法。这种机制称为类的继承。\n",
    "\n",
    "子类可以继承父类的所有公有属性和方法，也可以覆盖或扩展这些属性和方法。\n",
    "\n",
    "要定义一个子类，需要在类定义时使用冒号和括号将父类的名称括起来。\n",
    "\n",
    "例如，如果我们有一个名为\"Animal\"的类，我们可以创建一个该类的子类\"Dog\"："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "4ca80f54",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Animal:\n",
    "    def __init__(self, name):  # 构造函数\n",
    "        self.name = name  # 实例属性\n",
    "\n",
    "    def speak(self):  # 实例方法\n",
    "        print(\"{} is speak.\".format(self.name))\n",
    "        #pass\n",
    "\n",
    "class Dog(Animal):  # Dog是Animal的子类\n",
    "    def bark(self):  # 实例方法\n",
    "        print(\"Woof!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0383910c",
   "metadata": {},
   "source": [
    "在这个例子中，我们首先定义了一个名为\"Animal\"的类，然后创建了这个类的一个子类\"Dog\"。\n",
    "\n",
    "子类\"Dog\"继承了父类\"Animal\"的所有公有属性和方法，并添加了一个新的实例方法\"bark\"。\n",
    "\n",
    "子类可以继承父类的所有公有属性和方法，也可以重写或扩展这些属性和方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "212a750d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Woof!\n"
     ]
    }
   ],
   "source": [
    "dog = Dog(\"biger\")#创建一个实例类\n",
    "\n",
    "dog.bark()#调用自己的共有方法bark"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "ab71a22d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "biger is speak.\n"
     ]
    }
   ],
   "source": [
    "dog.speak()#调用父类的共有方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0fc9db2c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "549c5303",
   "metadata": {},
   "source": [
    "## 类的多态"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4069dc9f",
   "metadata": {},
   "source": [
    "在Python中，多态是指一个对象可以具有多种形态。\n",
    "\n",
    "这意味着，即使两个对象的类不同，它们也可以被视为相同的类型，并使用相同的方法调用方式。\n",
    "\n",
    "\n",
    "多态的实现依赖于继承和重写。\n",
    "\n",
    "*子类可以继承父类的方法，并对其进行重写以实现不同的行为。\n",
    "\n",
    "**当使用父类类型的变量引用子类对象时，将调用子类中的重写方法。\n",
    "\n",
    "例如，我们可以定义一个名为\"Animal\"的基类和一个名为\"Dog\"的子类，然后创建一个\"Animal\"类型的变量来引用一个\"Dog\"对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "44f5cab2",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Animal:\n",
    "    def __init__(self,name):\n",
    "        self.name=name\n",
    "    def speak(self):  # 实例方法\n",
    "        print(\"My name is \" + self.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "1cc0a4b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Dog(Animal):  # Dog是Animal的子类\n",
    "    def __init__(self,name):\n",
    "        self.name=name\n",
    "    def speak(self):  # 重写父类的speak方法\n",
    "        print(\"Woof!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "ba7b64db",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Woof!\n"
     ]
    }
   ],
   "source": [
    "dog1 = Dog(\"Goff\")# 创建一个Dog对象\n",
    "\n",
    "animal = dog1# 创建一个Animal类型的变量来引用dog1对象\n",
    "\n",
    "animal.speak()# 调用animal对象的speak方法，将调用Dog类的speak方法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82794e3b",
   "metadata": {},
   "source": [
    "在这个例子中，我们首先定义了一个名为\"Animal\"的基类和一个名为\"Dog\"的子类。子类\"Dog\"继承了父类\"Animal\"的\"speak\"方法，并对其进行了重写。然后，我们创建了一个名为\"dog1\"的\"Dog\"对象，并将其赋值给一个名为\"animal\"的\"Animal\"类型的变量。最后，我们调用了\"animal\"对象的\"speak\"方法，由于它是指向一个实际的\"Dog\"对象，因此将调用\"Dog\"类的重写后的\"speak\"方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "id": "3c595ba0",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Cat(Animal):\n",
    "    def __init__(self,name):\n",
    "        self.name=name\n",
    "    def speak(self):  # 重写父类的speak方法\n",
    "        print(\"Miao!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "dee1eb04",
   "metadata": {},
   "outputs": [],
   "source": [
    "cat1 = Cat(\"Tom\")# 创建一个Cat对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "d43eadc2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Miao!\n"
     ]
    }
   ],
   "source": [
    "cat1.speak()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "2ccf8c8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "animal=cat1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "cb9ed822",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Miao!\n"
     ]
    }
   ],
   "source": [
    "animal.speak()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac453fea",
   "metadata": {},
   "source": [
    "上述例子说明，animal这个对象有两种不同形态，一个是dog1，另一个是cat1，切换任何一个形态，都会重写父类speak的方法，因此调用这个方法时，一个对象可以有两种不同的行为，这取决于采用的是哪一种形态。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a231d568",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
